package com.bwie.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.User;
import com.bwie.common.domain.request.UserReqList;
import com.bwie.common.domain.request.UserReqLogin;
import com.bwie.common.domain.request.UserReqSendDelMessage;
import com.bwie.common.domain.request.UserReqSignUp;
import com.bwie.common.exceptions.BizException;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.common.utils.StringUtils;
import com.bwie.system.remote.RemoteMessageService;
import com.bwie.system.utils.SendSmsUtils;
import com.bwie.system.mapper.UserMapper;
import com.bwie.system.service.UserService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author Junchen_N1
 * @Date 2025/6/17 9:31
 * @ClassName UserServiceImpl
 * @Description TODO
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SendSmsUtils sendSmsUtils;

    /**
     * 用户名密码登录
     * @param userReqLogin
     * @return
     */
    @Override
    public Result<User> selectUserByUsernameAndPassword(UserReqLogin userReqLogin) {
        User userLogin = userMapper.selectUserByUsernameAndPassword(userReqLogin);
        return Result.success(userLogin);
    }

    /**
     * 查询登录用户的好友列表
     * @param userId
     * @return
     */
    @Override
    public Result<List<User>> selectUserFriendsListByUserId(Integer userId) {
        List<User> userList = userMapper.selectUserFriendsListByUserId(userId,null,null);
        return Result.success(userList);
    }

    /**
     * 发送短信验证码
     * @param tel
     */
    @Override
    public void sendSmsMsg(String tel) {
        //校验手机号是否重复
        User user = userMapper.selectUserByTel(tel);
        if (ObjectUtil.isNotEmpty(user)){
            throw new BizException("该手机号码已注册，请重试");
        }

        //生成验证码
        String code = RandomUtil.randomNumbers(4);
        //发送验证码
        SendSmsResponse sendSmsResponse = sendSmsUtils.sendSms(tel, JSON.toJSONString(new HashMap<String, String>() {{
            put("code", code);
        }}));

        //验证码存入redis
        redisTemplate.opsForValue().set(TokenConstants.SMS_CODE+code,1,5, TimeUnit.MINUTES);
    }

    /**
     * 用户名查询用户
     * @param username
     * @return
     */
    @Override
    public Result<User> selectUserByUsername(String username) {
        return Result.success(userMapper.selectUserByUsername(username));
    }

    /**
     * 手机号查询用户
     * @param tel
     * @return
     */
    @Override
    public Result<User> selectUserByTel(String tel) {
        return Result.success(userMapper.selectUserByTel(tel));
    }

    /**
     * 添加用户
     * @param userReqSignUp
     */
    @Override
    public void addUser(UserReqSignUp userReqSignUp) {
        userMapper.addUser(userReqSignUp);
    }

    /**
     * 查询登录用户好友列表 同步redis的set数据结构
     * @param userReqList
     * @return
     */
    @Override
    public Result<List<User>> selectFriendListByLoginUser(UserReqList userReqList) {
        User loginUserMsg = getLoginUserMsg();
        List<User> userList = null;
        if (Boolean.TRUE.equals(redisTemplate.hasKey(TokenConstants.FRIENDS_KEY + loginUserMsg.getUserId())) &&
            StringUtils.isBlank(userReqList.getRealName()) && null==userReqList.getSex()){
            String setJson = JSON.toJSONString(redisTemplate.opsForSet().members(TokenConstants.FRIENDS_KEY + loginUserMsg.getUserId()));
            userList = JSON.parseArray(setJson.substring(1,setJson.length()-1),User.class);
        }else {
            userList = userMapper.selectUserFriendsListByUserId(loginUserMsg.getUserId(), userReqList.getRealName(), userReqList.getSex());
            if (StringUtils.isBlank(userReqList.getRealName()) && null==userReqList.getSex()){
                redisTemplate.opsForSet().add(TokenConstants.FRIENDS_KEY+loginUserMsg.getUserId(),userList);
                redisTemplate.expire(TokenConstants.FRIENDS_KEY+loginUserMsg.getUserId(),30,TimeUnit.MINUTES);
            }
        }


        return Result.success(userList);
    }

    /**
     * 删除好友 延迟双删
     * @param friendId
     */
    @SneakyThrows
    @Override
    public void deleteFriend(Integer friendId) {
        //校验好友是否存在
        User user = userMapper.findById(friendId);
        if (ObjectUtil.isNull(user)){
            throw new BizException("该好友不存在");
        }

        //删除好友
        userMapper.deleteFriend(getLoginUserMsg().getUserId(),friendId);

        //使用延迟双删保证缓存一致性
        redisTemplate.delete(TokenConstants.FRIENDS_KEY+getLoginUserMsg().getUserId());
        Thread.sleep(500);
        redisTemplate.delete(TokenConstants.FRIENDS_KEY+getLoginUserMsg().getUserId());

        UserReqSendDelMessage userReqSendDelMessage = new UserReqSendDelMessage();
        userReqSendDelMessage.setUsername(getLoginUserMsg().getUsername());
        userReqSendDelMessage.setTel(user.getTel());
        //调用message服务发送消息
        RemoteMessageService.sendDelFriendMsg(userReqSendDelMessage);
    }

    /**
     * 查询不是当前登录用户的好友列表
     * @param userReqList
     * @return
     */
    @Override
    public Result<List<User>> selectNotMyFriendList(UserReqList userReqList) {
        userReqList.setUserId(getLoginUserMsg().getUserId());
        //查询好友关系表
        Integer count = userMapper.selectCountsByUserIdOfFriendUser(getLoginUserMsg().getUserId());
        if (count==0){
            return Result.success(userMapper.selectNotMyFriendListWithNoFriends(userReqList));
        }
        List<Integer> myFriendIdList = userMapper.selectMyFriendIdList(getLoginUserMsg().getUserId());
        return Result.success(userMapper.selectNotMyFriendList(userReqList,myFriendIdList));
    }

    /**
     * 添加好友
     * @param friendId
     */
    @SneakyThrows
    @Override
    public void addFriend(Integer friendId) {
        //查询好友是否存在
        User friendUser = userMapper.findById(friendId);
        if (ObjectUtil.isNull(friendUser)){
            throw new BizException("该好友不存在");
        }
        //添加好友
        userMapper.addFriend(getLoginUserMsg().getUserId(),friendId);

        //延迟双删保证数据一致性
        //使用延迟双删保证缓存一致性
        redisTemplate.delete(TokenConstants.FRIENDS_KEY+getLoginUserMsg().getUserId());
        Thread.sleep(500);
        redisTemplate.delete(TokenConstants.FRIENDS_KEY+getLoginUserMsg().getUserId());

    }

    /**
     * 登录用户信息
     * @return
     */
    @Override
    public User getLoginUserMsgToVue() {
        return userMapper.findById(getLoginUserMsg().getUserId());
    }

    /**
     * 回显
     * @param userId
     * @return
     */
    @Override
    public User findById(Integer userId) {
        return userMapper.findById(userId);
    }

    /**
     * 修改用户余额
     * @param userId
     * @param redPacketPrice
     * @param status
     */
    @Override
    public void updateUserBalance(Integer userId, BigDecimal redPacketPrice, Integer status) {
        userMapper.updateUserBalance(userId,redPacketPrice,status);
    }

    /**
     * 添加用户抢红包记录表
     * @param redPacketId
     * @param redPacketName
     * @param userId
     * @param username
     * @param snatchPrice
     */
    @Override
    public void addRedPacketReceived(Integer redPacketId, String redPacketName, Integer userId, String username, BigDecimal snatchPrice) {
        userMapper.addRedPacketReceived(redPacketId,redPacketName,userId,username,snatchPrice);
    }

    /**
     * 根据用户id和红包id统计中间表记录数
     * @param userId
     * @param redPacketId
     * @return
     */
    @Override
    public Integer findByIdOfUserRedPacketReceive(Integer userId, Integer redPacketId) {
        return userMapper.findByIdOfUserRedPacketReceive(userId,redPacketId);
    }

    /**
     * 登录用户信息
     * @return
     */
    private User getLoginUserMsg() {
        String token = request.getHeader(TokenConstants.TOKEN);
        String userKey = JwtUtils.getUserKey(token);
        User loginUser = (User) redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey);
        if (ObjectUtil.isEmpty(loginUser)){
            throw new BizException("用户信息已过期");
        }
        return loginUser;
    }


}
